package com.cc.flyingfish.websocket;

/**
 * @author CHENCHEN
 * @title
 * @createTime 2023-03-12 18:36
 */

import com.alibaba.fastjson.JSONObject;
import com.cc.flyingfish.entity.Danmu;
import com.cc.flyingfish.service.DanMuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Component
@ServerEndpoint("/ffserver/{token}")
public class WebSocketService {

    //JDK提供线程安全并发的Integer
    private static final AtomicInteger ONLINE_COUNT = new AtomicInteger(0);
    //使用多例模式，创建不同的WebSocketService对象
    private static final ConcurrentHashMap<String, WebSocketService> WEBSOCKET_MAP = new ConcurrentHashMap<>();
    //创建客户端与服务端会话（WebSocket ——> session）
    private Session session;
    //会话唯一标识
    private String sessionId;

    private Long userId;

    private static ApplicationContext APPLICATIONCONTEXT;

    public static void setApplicationContext(ApplicationContext applicationContext){
        WebSocketService.APPLICATIONCONTEXT = applicationContext;
    }


    //开启链接方法
    @OnOpen
    public void openConnection(Session session, @PathParam("token") String token){
        try{
            //LoginUserInfo loginUserInfo = TokenParseUtil.parseUserInfoFromToken(token);
            //this.userId = loginUserInfo.getUserId();
            this.userId = 999L;
        }catch (Exception e){}
        this.sessionId = session.getId();
        this.session = session;
        //判断当前是否有sessionId
        if(WEBSOCKET_MAP.containsKey(sessionId)){
            WEBSOCKET_MAP.remove(sessionId);
            WEBSOCKET_MAP.put(sessionId, this);
        }else{
            WEBSOCKET_MAP.put(sessionId, this);
            //如果是第一次创建，在线人数 +1
            ONLINE_COUNT.getAndIncrement();
        }
        log.info("用户链接成功，在线人数为：[{}] 人",ONLINE_COUNT.get());
        try{
            //通知前端链接成功或者失败

        }catch (Exception e){
            //通知前端链接失败

        }
    }

    //关闭退出
    @OnClose
    public void closeConnection(){
        if(WEBSOCKET_MAP.containsKey(sessionId)){
            WEBSOCKET_MAP.remove(sessionId);
            //在线人数 -1
            ONLINE_COUNT.getAndDecrement();
        }
        log.info("用户退出，在线人数为：[{}] 人",ONLINE_COUNT.get());
    }

    //获取前端发送消息方法
    @OnMessage
    public void onMessage(String message){
        log.info("用户标识 ：[{}], 报文 ：[{}]", sessionId, message);
        if(!StringUtils.isEmpty(message)){
            try{
                for (Map.Entry<String, WebSocketService> entry: WEBSOCKET_MAP.entrySet()) {
                    WebSocketService webSocketService = entry.getValue();
                    if (webSocketService.session.isOpen()) {
                        webSocketService.sendMessage(message);
                    }
                }
                if(this.userId != null){
                    Danmu danmu = JSONObject.parseObject(message, Danmu.class);
                    danmu.setUserId(this.userId);
                    danmu.setCreateTime(new Date());
                    //获取多例 DanMuService 实现
                    DanMuService danMuService = (DanMuService) APPLICATIONCONTEXT.getBean("danMuService");
                    //保存弹幕到 Redis 中
                    danMuService.addDanMuToRedis(danmu);
                }
            }catch (Exception e){

            }
        }
    }

    //出现异常方法
    @OnError
    public void onError(Throwable throwable){

    }

    //发送消息方法
    public void sendMessage(String message) throws Exception {
        this.session.getBasicRemote().sendText(message);
    }
}
